package com.huatai.bi.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huatai.bi.dto.DataTableSynPrarmDto;
import com.huatai.bi.entity.DatasourceEntity;
import com.huatai.bi.entity.TableColumnEntity;
import com.huatai.bi.entity.TableEntity;
import com.huatai.bi.handler.DatasourceHandler;
import com.huatai.bi.mapper.TableColumnMapper;
import com.huatai.bi.mapper.TableMapper;
import com.huatai.bi.query.TableQuery;
import com.huatai.bi.service.DatasourceService;
import com.huatai.bi.service.TableColumnService;
import com.huatai.bi.service.TableService;
import com.huatai.bi.vo.TablesVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TableServiceImpl extends ServiceImpl<TableMapper, TableEntity> implements TableService {

    @Lazy
    @Autowired
    DatasourceService datasourceService;
    @Autowired
    TableColumnService tableColumnService;
    @Autowired
    TableColumnMapper tableColumnMapper;

    @Override
    public List<TableEntity> list(TableQuery query) {
        //列表根据数据源和表名排序
        LambdaQueryWrapper<TableEntity> qw = Wrappers.lambdaQuery();
        qw.like(StringUtils.isNotBlank(query.getName()), TableEntity::getTableName, query.getName());
        qw.eq(null != query.getDatasourceId(), TableEntity::getDatasourceId, query.getDatasourceId());
        qw.orderBy(true, true, TableEntity::getDatasourceId, TableEntity::getTableName);
        List<TableEntity> list = super.list(qw);
        buildExInfo(list);
        return list;
    }

    public Page page(TableQuery query) {
        int pageIndex = 1;
        int pageSize = 10;
        if (null != query.getPageIndex() && null != query.getPageSize()) {
            pageIndex = query.getPageIndex() > 0 ? query.getPageIndex() : 1;
            pageSize = query.getPageSize() > 0 ? query.getPageSize() : 10;
        }
        LambdaQueryWrapper<TableEntity> qw = Wrappers.lambdaQuery();
        qw.like(StringUtils.isNotBlank(query.getName()), TableEntity::getTableName, query.getName());
        qw.eq(null != query.getDatasourceId(), TableEntity::getDatasourceId, query.getDatasourceId());
        qw.orderBy(true, true, TableEntity::getDatasourceId, TableEntity::getTableName);
        Page page = page(new Page<TableEntity>(pageIndex<1?1:pageIndex, pageSize<1?10:pageSize), qw);
        buildExInfo(page.getRecords());
        return page;
    }

    @Override
    public void buildExInfo(TableEntity data) {
        if (null == data) {
            return;
        }
        DatasourceEntity entity = datasourceService.getById(data.getDatasourceId());
        if (null != entity) {
            data.setDatasourceName(entity.getName());
        }
    }

    @Override
    public void buildExInfo(List<TableEntity> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        List<DatasourceEntity> datasourceList = datasourceService.list();
        if (CollectionUtils.isEmpty(datasourceList)) {
            return;
        }
        //数据源ID和数据源名称作为map,设置数据源名称
        Map<Long, String> map = datasourceList.stream().collect(Collectors.toMap(DatasourceEntity::getId, DatasourceEntity::getName));
        list.stream().forEach(item -> {
            item.setDatasourceName(map.get(item.getDatasourceId()));
        });
    }


    //@Async("asyncServiceExecutor")
    public void initTable(DatasourceEntity entity) {

        //根据数据源ID删除表和表字段数据
        deleteByDatasourceId(entity.getId());
        //查询数据源下表信息
        DatasourceHandler datasource = DatasourceHandler.datasourceFactory(entity);
        List<TableEntity> tableList = datasource.getTables();
        tableList.stream().forEach(item -> {
            item.setDatasourceId(entity.getId());
        });
        saveBatch(tableList);
        //查询表字段信息
        Map<String, Long> tableNameMap = tableList.stream().collect(Collectors.toMap(TableEntity::getTableName, TableEntity::getId));
        List<TableColumnEntity> columnList = datasource.getTableColumns();
        datasource.closeConn();
        columnList.stream().forEach(item -> {
            item.setDatasourceId(entity.getId());
            item.setTableId(tableNameMap.get(item.getTableName()));
        });
        tableColumnService.saveBatch(columnList);
        datasource.closeConn();
        //更新表字段数
        super.baseMapper.updateColumnNum(entity.getId());

    }

    public void deleteByDatasourceId(Long datasourceId) {
        super.baseMapper.deleteByDatasourceId(datasourceId);
        tableColumnMapper.deleteByDatasourceId(datasourceId);
    }

    /**
     * 获取表数据
     *
     * @param synPrarmDto
     * @return
     */
    public List<TablesVo> getTables(DataTableSynPrarmDto synPrarmDto) {

        QueryWrapper<TableEntity> query = Wrappers.query();
        query.in("a.id",synPrarmDto.getTableIds());
        query.eq("a.is_deleted", 0);
        List<JSONObject> tables = baseMapper.getTables(synPrarmDto.getDtId(),query);
        if (CollectionUtils.isEmpty(tables)) {
            return Collections.emptyList();
        }
        List<TablesVo> tablesVos = new ArrayList<>();
        tables.forEach(table -> {
            TablesVo tablesVo=new TablesVo();
            tablesVo.setTableId(table.getLong("id"));
            String tableName= table.getString("table_name").toLowerCase();
            tablesVo.setTableName(tableName);
            //随机获取表后缀
            String target_table = table.getString("target_table");
            tablesVo.setTargetTableName("db_"+table.getString("dtname")+"_"+tableName+"_"+ IdWorker.getId());
            tablesVo.setTargetUsedTableName(target_table);
            tablesVos.add(tablesVo);
        });
        return tablesVos;
    }

    /**
     * 获取改表是否已存在数据集tb_direct_data_set
     * @param tableId
     * @param tableName
     * @return
     */
    public int getDataSetNum(Long tableId, String tableName) {
        return baseMapper.getDataSetNum(tableId,tableName);
    }

    @Override
    public void updateByDatasourceId(Long datasourceId){
        DatasourceEntity datasource = datasourceService.getDecodeData(datasourceId);
        if(null == datasource){
            return;
        }
        //获取原始数据
        LambdaQueryWrapper<TableEntity> tableQw = Wrappers.lambdaQuery();
        tableQw.eq(TableEntity::getDatasourceId,datasourceId);
        List<TableEntity> oldTableList = list(tableQw);
        //将列表使用表名转为map
        Map<String,TableEntity> oldTableMap = oldTableList.stream().collect(Collectors.toMap(TableEntity::getTableName, Function.identity()));

        LambdaQueryWrapper<TableColumnEntity> columnQw = Wrappers.lambdaQuery();
        columnQw.eq(TableColumnEntity::getDatasourceId,datasourceId);
        List<TableColumnEntity> oldColumnList = tableColumnService.list(columnQw);
        tableColumnService.buildExInfo(oldColumnList);
        //使用表名+字段名作为key将字段列表转为map
        Map<String, TableColumnEntity> oldTableColumnMap = new HashMap<>();
        oldColumnList.stream().forEach(item -> {
            String key = item.getTableName()+":"+item.getColumnName();
            oldTableColumnMap.put(key,item);
        });

        DatasourceHandler handler = DatasourceHandler.datasourceFactory(datasource);
        List<TableEntity> tables = handler.getTables();

        tables.stream().forEach(table -> {
            TableEntity oldTable = oldTableMap.remove(table.getTableName());
            if(null != oldTable){
                table.setId(oldTable.getId());
            }
            table.setDatasourceId(datasourceId);
        });

        //删除不存在的表
        if(oldTableMap.size() > 0){
            removeBatchByIds(oldTableMap.values());
        }

        saveOrUpdateBatch(tables);

        Map<String, Long> tableNameMap = tables.stream().collect(Collectors.toMap(TableEntity::getTableName, TableEntity::getId));

        List<TableColumnEntity> tableColumns = handler.getTableColumns();
        handler.closeConn();
        tableColumns.stream().forEach( column -> {
            String key = column.getTableName()+":"+column.getColumnName();
            TableColumnEntity old = oldTableColumnMap.remove(key);
            if(null != old){
                column.setId(old.getId());
            }
            column.setDatasourceId(datasourceId);
            column.setTableId(tableNameMap.get(column.getTableName()));
        });
        if(oldTableColumnMap.size() > 0){
            tableColumnService.removeBatchByIds(oldTableColumnMap.values());
        }
        tableColumnService.saveOrUpdateBatch(tableColumns);
        //更新表字段数
        super.baseMapper.updateColumnNum(datasourceId);
    }
}
